<template>
  <div>
    <a-row type="flex" :gutter="10">
      <a-col :span="12">
        <a-card :bordered="false" style="min-height: calc(100vh - 125px)">
          <advance-table
            :columns="columns"
            :data-source="list"
            title="角色管理"
            :loading="loading"
            rowKey="id"
            size="middle"
            tableKey="system-role-SysRoleIndex-table"
            @refresh="getList"
            :customRow="onClickRow"
            :format-conditions="true"
            :row-selection="{
              selectedRowKeys: selectedRowKeys,
              onChange: onSelectChange,
            }"
            :pagination="{
              current: queryParam.pageNum,
              pageSize: queryParam.pageSize,
              total: total,
              showSizeChanger: true,
              showLessItems: true,
              showQuickJumper: true,
              showTotal: (total, range) =>
                `第 ${range[0]}-${range[1]} 条，总计 ${total} 条`,
              onChange: changeSize,
              onShowSizeChange: onShowSizeChange,
            }"
          >
            <div class="table-operations" slot="button">
              <a-input-search
                placeholder="请输入编码或名称"
                v-model="queryParam.codeOrName"
                style="width: 150px"
                @search="handleQuery"
              />
              <a-button
                type="primary"
                size="small"
                @click="addRow()"
                v-hasPermi="['system:role:add']"
              >
                <a-icon type="plus" />新增
              </a-button>
              <a-button
                type=""
                size="small"
                @click="batchSaveRole()"
                v-hasPermi="['system:role:add']"
              >
                <a-icon type="save" />保存
              </a-button>
              <a-button
                type="danger"
                v-if="!multiple"
                @click="batchDeleteRow"
                v-hasPermi="['system:role:remove']"
              >
                <a-icon type="delete" />删除
              </a-button>
              <a-button
                type=""
                @click="handleExport"
                v-hasPermi="['system:role:export']"
              >
                <a-icon type="download" />导出
              </a-button>
            </div>
            <span slot="status" slot-scope="{ record }">
              <a-tooltip placement="top">
                <template slot="title">
                  <span>点击修改状态</span>
                </template>
                <a-popconfirm
                  ok-text="是"
                  cancel-text="否"
                  @confirm="confirmHandleStatus(record)"
                >
                  <span slot="title"
                    >确认<b>{{ record.status === "1" ? "启用" : "停用" }}</b
                    >【{{ record.roleName }}】的角色吗?</span
                  >
                  <a-badge
                    :status="record.status === '0' ? 'processing' : 'error'"
                    :text="statusFormat(record)"
                  />
                </a-popconfirm>
              </a-tooltip>
            </span>

            <span slot="roleNameSolt" slot-scope="{ text, record }">
              <a-tag color="blue" v-if="!record.editable">
                {{ text }}
              </a-tag>
              <a-input
                placeholder="请输入"
                v-model="record.roleName"
                v-if="record.editable"
              />
            </span>
            <span slot="roleKey" slot-scope="{ text, record }">
              <a-tag
                color="blue"
                v-if="!record.editable || record.roleKey === 'admin'"
              >
                {{ text }}
              </a-tag>
              <a-input
                placeholder="请输入"
                v-model="record.roleKey"
                v-if="record.editable && record.roleKey !== 'admin'"
              />
            </span>
            <span slot="sort" slot-scope="{ text, record }">
              <span v-if="!record.editable">
                {{ text }}
              </span>
              <a-input-number
                placeholder="请输入"
                v-model="record.sort"
                v-if="record.editable"
                :min="0"
                style="width: 100%"
              />
            </span>
            <span slot="operation" slot-scope="{ record }">
              <div v-if="record.editable">
                <a @click.stop="cancelEditCell(record)"> 取消 </a>
                <a-divider type="vertical" />
                <a @click="deleteRow(record, 'delete')">删除</a>
              </div>
              <div v-else>
                <a
                  @click.stop="updateRow(record)"
                  v-hasPermi="['system:role:edit']"
                >
                  修改
                </a>
                <a-divider
                  type="vertical"
                  v-hasPermi="['system:role:remove']"
                />
                <a
                  @click.stop="deleteRow(record)"
                  v-hasPermi="['system:role:remove']"
                >
                  删除
                </a>
              </div>
            </span>
          </advance-table>
        </a-card>
      </a-col>
      <a-col :span="12">
        <a-card :bordered="false" style="min-height: calc(100vh - 125px)">
          <select-user
            selectModel="multi"
            v-model="selectedUser"
            v-show="false"
            ref="selectUserRef"
          />
          <advance-table
            :columns="roleUserColumns"
            :data-source="subList"
            title="角色用户"
            :loading="subLoading"
            rowKey="id"
            size="middle"
            tableKey="system-roleuser-SysRoleIndex-table"
            @refresh="getRoleUserList"
            :format-conditions="true"
            :row-selection="{
              selectedRowKeys: selectedSubRowKeys,
              onChange: onSelectSubChange,
            }"
            :pagination="{
              current: querySubParam.pageNum,
              pageSize: querySubParam.pageSize,
              total: subTotal,
              showSizeChanger: true,
              showLessItems: true,
              showQuickJumper: true,
              showTotal: (subTotal, range) =>
                `第 ${range[0]}-${range[1]} 条，总计 ${subTotal} 条`,
              onChange: changeSubSize,
              onShowSizeChange: onShowSizeSubChange,
            }"
          >
            <div class="table-operations" slot="button">
              <a-input-search
                placeholder="请输入编码或名称"
                v-model="querySubParam.userNameOrName"
                style="width: 150px"
                @search="handleQueryRoleUser"
              />
              <a-button
                type="primary"
                v-if="currentSelectRoleId.indexOf('newRow-') < 0"
                size="small"
                @click="handleAddUser()"
                v-hasPermi="['system:role:add']"
              >
                <a-icon type="plus" />添加用户
              </a-button>
              <a-button
                type="danger"
                v-if="!subMultiple"
                @click="handleDeleteSub"
                v-hasPermi="['system:role:remove']"
              >
                <a-icon type="delete" />删除
              </a-button>
            </div>

            <span slot="status" slot-scope="{ record }">
              <a-badge status="processing" :text="statusFormat(record)" />
            </span>
            <span slot="roleKey" slot-scope="{ text }">
              <a-tag color="blue">
                {{ text }}
              </a-tag>
            </span>
            <span slot="operation" slot-scope="{ record }">
              <a
                @click.stop="handleDeleteSub(record)"
                v-hasPermi="['system:role:remove']"
              >
                删除
              </a>
            </span>
          </advance-table>
        </a-card>
      </a-col>
    </a-row>
  </div>
</template>
<script>
import {
  listRole,
  exportRole,
  batchSaveRole,
  delRoleUser,
  changeRoleStatus,
} from "@/api/system/role";
import { getRoleUserList, saveRoleUser } from "@/api/system/user";
import AdvanceTable from "@/components/pt/table/AdvanceTable";
import SelectUser from "@/components/pt/selectUser/SelectUser";
import { randomUUID } from "@/utils/util";
export default {
  name: "Role",
  components: {
    AdvanceTable,
    SelectUser,
  },
  data() {
    return {
      list: [],
      // 表格缓存的数据 - 用来点击取消时回显数据
      cacheData: [],
      deleteData: [], // 可编辑表格待删除数据，数据库已存在数据界面假删除，保存到该集合，最终请求数据库删除
      subList: [],
      selectedRowKeys: [],
      selectedSubRowKeys: [],
      selectedRows: [],
      selectedSubRows: [],
      selectedUser: "",
      // 高级搜索 展开/关闭
      advanced: false,
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      subMultiple: true,
      currentSelectRoleId: "",
      selectItem: {},
      ids: [],
      subIds: [], // 子表选择id集合
      loading: false,
      subLoading: false,
      total: 0,
      subTotal: 0,
      // 状态数据字典
      statusOptions: [],
      // 日期范围
      dateRange: [],
      labelCol: {
        span: 6,
      },
      wrapperCol: {
        span: 18,
      },
      queryParam: {
        pageNum: 1,
        pageSize: 10,
        roleName: undefined,
        roleKey: undefined,
        status: undefined,
      },
      querySubParam: {
        pageNum: 1,
        pageSize: 10,
      },
      addModalRefName: "addModal", // 添加弹窗ref名称
      columns: [
        {
          title: "角色名称",
          dataIndex: "roleName",
          ellipsis: true,
          scopedSlots: {
            customRender: "roleNameSolt",
          },
        },
        {
          title: "角色编码",
          dataIndex: "roleKey",
          width: "150px",
          ellipsis: true,
          scopedSlots: {
            customRender: "roleKey",
          },
        },
        {
          title: "排序号",
          dataIndex: "sort",
          align: "center",
          scopedSlots: {
            customRender: "sort",
          },
        },
        {
          title: "状态",
          dataIndex: "status",
          scopedSlots: {
            customRender: "status",
          },
          align: "center",
        },
        {
          title: "操作",
          dataIndex: "operation",
          width: "100px",
          scopedSlots: {
            customRender: "operation",
          },
        },
      ],
      roleUserColumns: [
        {
          title: "用户名称",
          dataIndex: "name",
          ellipsis: true,
        },
        {
          title: "登录名",
          dataIndex: "userName",
          ellipsis: true,
        },
        {
          title: "状态",
          dataIndex: "status",
          scopedSlots: {
            customRender: "status",
          },
          align: "center",
        },
        {
          title: "操作",
          dataIndex: "operation",
          width: "100px",
          scopedSlots: {
            customRender: "operation",
          },
        },
      ],
    };
  },
  filters: {},
  created() {
    this.getList();
    this.getDicts("sys_normal_disable").then((response) => {
      this.statusOptions = response.data;
    });
  },
  computed: {},
  watch: {
    selectedUser(val) {
      const saveRoleUserForm = {
        userId: val.ids,
        roleId: this.currentSelectRoleId,
      };
      saveRoleUser(saveRoleUserForm).then((response) => {
        this.$message.success("添加成功", 3);
        this.getRoleUserList();
      });
    },
    selectItem(val) {
      this.renderRowStyle(val);
      this.getRoleUserList(val.id);
    },
  },
  methods: {
    statusFormat(row) {
      return this.selectDictLabel(this.statusOptions, row.status);
    },
    /** 查询定时任务列表 */
    getList() {
      this.showAddModal = false;
      this.showEditModal = false;
      this.showDataScopeModal = false;
      this.loading = true;
      listRole(this.addDateRange(this.queryParam, this.dateRange)).then(
        (response) => {
          this.list = response.data.list;
          this.list.map((item) => {
            item.operation = item.remark;
          });
          this.total = response.data.total;
          this.loading = false;
          if (this.list.length > 0) {
            this.$nextTick(() => (this.selectItem = this.list[0]));
            // this.getRoleUserList(this.list[0].id)
          }
        }
      );
    },
    getRoleUserList(roleId) {
      if (typeof roleId === "string") {
        if (roleId === null || roleId === "" || roleId === undefined) {
          roleId = this.currentSelectRoleId;
        } else {
          this.currentSelectRoleId = roleId;
        }
      } else {
        roleId = this.currentSelectRoleId;
      }
      if (roleId.indexOf("newRow-") < 0) {
        // 只有保存的数据才加载字表数据
        this.subLoading = true;
        this.querySubParam.roleId = roleId;
        getRoleUserList(
          this.addDateRange(this.querySubParam, this.dateRange)
        ).then((response) => {
          this.subList = response.data.list;
          this.subList.map((item) => {
            item.operation = item.remark;
          });
          this.subTotal = response.data.total;
          this.subLoading = false;
        });
      } else {
        // 新添加行不需要加载后台，直接清空子表数据
        this.subList = [];
        this.subTotal = 0;
      }
      this.subIds = [];
      this.selectedSubRowKeys = [];
      this.subMultiple = true;
    },
    onClickRow(record, index) {
      return {
        on: {
          click: (event) => {
            if (event.target !== undefined && event.target.localName === "td") {
              if (this.validaData()) {
                this.selectItem = record;
                // this.updateRow(record)
              }
            }
          },
        },
      };
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParam.pageNum = 1;
      this.getList();
    },
    handleQueryRoleUser() {
      this.querySubParam.pageNum = 1;
      this.getRoleUserList();
    },
    addRow() {
      const flag = this.validaData();
      if (flag) {
        // 角色添加行方法
        const id = randomUUID();
        const newRow = {
          id: "newRow-" + id, // newRow 表示该行是新增的，提交成功后 key替换为数据库ID
          handleType: "add",
          roleName: "",
          roleKey: "",
          status: "0",
          operation: "",
          editable: true,
        };
        // 关闭所有已打卡行编辑
        this.closeEditCell(this.list);
        this.list.unshift(newRow);
        this.$nextTick(() => (this.selectItem = newRow));
      }
    },
    updateRow(record) {
      // if (record.roleKey === 'admin') {
      //   this.$message.info('管理员不允许修改！')
      // } else {
      // 角色编辑行方法
      const newData = [...this.list];
      this.closeEditCell(newData);
      record.handleType = "edit";
      record.editable = true;
      this.list = newData;
      // this.getRoleUserList(record.id)
      this.$nextTick(() => (this.selectItem = record));
      // }
    },
    cancelEditCell(record) {
      if (this.validaData()) {
        // 取消行编辑
        const newData = [...this.list];
        record.editable = false;
        this.list = newData;
      }
    },
    realDeleteRow(record, type) {
      if (record.roleKey === "admin") {
        this.$message.info("管理员不允许删除！");
      } else {
        const newData = [...this.list];
        const id = record.id;
        record.handleType = "delete";
        if (id.indexOf("newRow-") < 0) {
          // 数据库数据需要保存到待删除集合最终提交数据库删除
          this.deleteData.push(record);
        }
        const target = newData.filter((item) => record.id !== item.id);
        if (target) {
          this.list = target;
        }
        if (type !== "batch") {
          this.selectFirstRecord();
        }
      }
    },
    deleteRow(record, type) {
      if (type !== "batch") {
        const id = record.id;
        if (id.indexOf("newRow-") >= 0) {
          // 针对前台添加为保存数据库的数据直接删除，无需询问
          this.realDeleteRow(record, type);
        } else {
          const that = this;
          this.$confirm({
            title: "删除角色会删除相关的菜单，用户关系等，确认删除吗?",
            onOk() {
              that.realDeleteRow(record, type);
            },
            onCancel() {},
          });
        }
      } else {
        this.realDeleteRow(record, type);
      }
    },
    batchDeleteRow() {
      const that = this;
      this.$confirm({
        title: "删除角色会删除相关的菜单，用户关系等，确认删除吗?",
        // content: '当前选中编号为' + roleIds + '的数据',
        onOk() {
          that.ids.forEach((id) => {
            const deleteRowData = that.list.filter((item) => id === item.id)[0];
            that.deleteRow(deleteRowData, "batch");
          });
          that.selectFirstRecord();
        },
        onCancel() {},
      });
    },
    selectFirstRecord() {
      // 定位选中行到第一条数据
      if (this.list.length > 0) {
        this.selectItem = this.list[0];
      } else {
        // 移除子表数据
        this.subList = [];
        this.subTotal = 0;
      }
    },
    batchSaveRole() {
      // 批量保存角色数据
      let saveList = this.list.filter(
        (item) => item.handleType === "add" || item.handleType === "edit"
      );
      saveList = saveList.concat(this.deleteData);
      if (saveList.length === 0) {
        this.$message.info("没有可保存的数据！");
      } else {
        const flag = this.validaData();
        if (flag) {
          batchSaveRole(saveList).then((response) => {
            this.$message.success("保存成功", 3);
            this.getList();
          });
        }
      }
    },
    validaData() {
      let flag = true;
      this.list.forEach((item) => {
        if (
          item.handleType !== "undefined" &&
          (item.handleType === "add" || item.handleType === "edit")
        ) {
          if (
            item.roleName === "" ||
            item.roleName === "undefined" ||
            item.roleName === null
          ) {
            this.$message.info("请先维护角色名称为空的数据！");
            flag = false;
          }
          if (
            flag &&
            (item.roleKey === "" ||
              item.roleKey === "undefined" ||
              item.roleKey === null)
          ) {
            this.$message.info("请先维护角色编码为空的数据！");
            flag = false;
          }
        }
      });
      return flag;
    },
    closeEditCell(data) {
      // 关闭所有打开的可编辑行
      const list = data.filter((item) => item.editable === true);
      list.forEach((item) => {
        item.editable = false;
      });
    },
    /* 角色状态修改 */
    confirmHandleStatus(row) {
      const text = row.status === "1" ? "启用" : "停用";
      row.status = row.status === "0" ? "1" : "0";
      changeRoleStatus(row.id, row.status)
        .then(() => {
          this.$message.success(text + "成功", 3);
        })
        .catch(function () {
          this.$message.error(text + "异常", 3);
        });
    },
    handleAddUser() {
      this.$nextTick(() => this.$refs.selectUserRef.showSelectUser());
    },
    onShowSizeChange(current, pageSize) {
      this.queryParam.pageSize = pageSize;
      this.getList();
    },
    onShowSizeSubChange(current, pageSize) {
      this.querySubParam.pageSize = pageSize;
      this.getRoleUserList();
    },
    onSizeChange(current, size) {
      this.queryParam.pageNum = 1;
      this.queryParam.pageSize = size;
      this.getList();
    },
    changeSize(current, pageSize) {
      this.queryParam.pageNum = current;
      this.queryParam.pageSize = pageSize;
      this.getList();
    },
    changeSubSize(current, pageSize) {
      this.querySubParam.pageNum = current;
      this.querySubParam.pageSize = pageSize;
      this.getRoleUserList();
    },
    onSelectChange(selectedRowKeys, selectedRows) {
      this.selectedRowKeys = selectedRowKeys;
      this.selectedRows = selectedRows;
      this.ids = this.selectedRows.map((item) => item.id);
      this.single = selectedRowKeys.length !== 1;
      this.multiple = !selectedRowKeys.length;
    },
    onSelectSubChange(selectedSubRowKeys, selectedSubRows) {
      this.selectedSubRowKeys = selectedSubRowKeys;
      this.selectedSubRows = selectedSubRows;
      this.subIds = this.selectedSubRows.map((item) => item.id);
      this.subMultiple = !selectedSubRowKeys.length;
    },
    handleDeleteSub(row) {
      var that = this;
      const userIds = row.id || this.subIds;
      this.$confirm({
        title: "确认删除所选中数据?",
        onOk() {
          return delRoleUser(that.currentSelectRoleId, userIds).then(() => {
            that.onSelectSubChange([], []);
            that.getRoleUserList();
            that.$message.success("删除成功", 3);
          });
        },
        onCancel() {},
      });
    },
    /** 导出按钮操作 */
    handleExport() {
      var that = this;
      this.$confirm({
        title: "是否确认导出?",
        content: "此操作将导出当前条件下所有数据而非选中数据",
        onOk() {
          return exportRole(that.queryParam).then((response) => {
            that.download(response.msg);
            that.$message.success("导出成功", 3);
          });
        },
        onCancel() {},
      });
    },
    renderRowStyle(currentRow) {
      // 增加表格选中行样式
      // 类数组
      const rowEles = document.getElementsByClassName("ant-table-row");
      const rowSelectEles = document.getElementsByClassName("row-selection");
      let rowList;
      if (rowSelectEles.length) {
        rowSelectEles[0].classList.remove("row-selection");
      }
      if (rowEles.length) {
        rowList = [...rowEles];
        // 这里不用 === 是因为获取的 rowKey 是 String 类型，而给与的原数据 key 为 Number 类型
        // 若要用 === ，事先进行类型转换再用吧
        rowList
          .find((row) => row.dataset.rowKey === currentRow.id)
          .classList.add("row-selection");
      }
    },
  },
};
</script>
<style lang="less">
.ant-table-row.row-selection {
  background-color: #f0f2f5;
}
</style>
